#pragma once 


#include <memory>
#include <semaphore.h>
namespace TinyRPC{

/**
 * 
 * Future对象 功能类似于std::future, future.get() 只有当值被设置是才可以
 * Future对象本身是可以被复制的, 因为其内部有一个实际对象 FutureImpl
 */

template<typename T>
class Future{
public:
    Future()
    : m_future(std::make_shared<FutureImpl>())
    {
        
    }
    
    //没有完成就线程就阻塞等待
    T& get(){
        while(true){
            if(m_future->m_done){
                return m_future->m_val;
            }else{
                sem_wait(&m_future->m_sem);
            }
        }
    }
    // 直接获得
    T& getUnsafe(){
        return m_future->m_val;
    }

    void set(T val){
        m_future->m_val = val;
        m_future->m_done = true;
        sem_post(&m_future->m_sem);
    }

    void setDone(){
        m_future->m_done = true;
        sem_post(&m_future->m_sem);
    }

    
private:

    class FutureImpl{
    public:
        FutureImpl()
        : m_done(false)
        {
            sem_init(&m_sem,0,0);
        }
        ~FutureImpl(){
            sem_destroy(&m_sem);
        }
        T m_val;
        sem_t m_sem;
        bool m_done;
    };

    std::shared_ptr<FutureImpl> m_future;
};

// 通过shared_ptr 获得Future
template<typename T>
using FuturePtr = std::shared_ptr<Future<T>> ;
}